//
// Created by Admin on 2024/1/3.
//

#ifndef RTPPARSER_RTPPARSER_H
#define RTPPARSER_RTPPARSER_H
#include <memory>
#include <string>
#include <string.h>

#if defined(_WIN32)
#ifndef ssize_t
    #ifdef _WIN64
        #define ssize_t int64_t
    #else
        #define ssize_t int32_t
    #endif
#endif
#endif//WIN32

#if defined(__MACH__)
#include <arpa/inet.h>
#include <machine/endian.h>
#define __BYTE_ORDER BYTE_ORDER
#define __BIG_ENDIAN BIG_ENDIAN
#define __LITTLE_ENDIAN LITTLE_ENDIAN
#elif defined(__linux__)
#include <arpa/inet.h>
#include <endian.h>
#elif defined(_WIN32)
#define BIG_ENDIAN 1
#define LITTLE_ENDIAN 0
#define BYTE_ORDER LITTLE_ENDIAN
#define __BYTE_ORDER BYTE_ORDER
#define __BIG_ENDIAN BIG_ENDIAN
#define __LITTLE_ENDIAN LITTLE_ENDIAN
#endif

#pragma pack(push, 1)

enum { kRtpVersion = 2, kRtpHeaderSize = 12, kRtpTcpHeaderSize = 4 };

class RtpHeader {
public:
#if __BYTE_ORDER == __BIG_ENDIAN
    // 版本号，固定为2
    uint32_t version : 2;
    // padding
    uint32_t padding : 1;
    // 扩展
    uint32_t ext : 1;
    // csrc
    uint32_t csrc : 4;
    // mark
    uint32_t mark : 1;
    // 负载类型
    uint32_t pt : 7;
#else
    // csrc
    uint32_t csrc : 4;
    // 扩展
    uint32_t ext : 1;
    // padding
    uint32_t padding : 1;
    // 版本号，固定为2
    uint32_t version : 2;
    // 负载类型
    uint32_t pt : 7;
    // mark
    uint32_t mark : 1;
#endif
    // 序列号
    uint32_t seq : 16;
    // 时间戳
    uint32_t stamp;
    // ssrc
    uint32_t ssrc;
    // 负载，如果有csrc和ext，前面为 4 * csrc + (4 + 4 * ext_len)
    uint8_t payload;

public:
    // 返回csrc字段字节长度
    size_t getCsrcSize() const;
    // 返回csrc字段首地址，不存在时返回nullptr
    uint8_t *getCsrcData();

    // 返回ext字段字节长度
    size_t getExtSize() const;
    // 返回ext reserved值
    uint16_t getExtReserved() const;
    // 返回ext段首地址，不存在时返回nullptr
    uint8_t *getExtData();

    // 返回有效负载指针,跳过csrc、ext
    uint8_t *getPayloadData();
    // 返回有效负载总长度,不包括csrc、ext、padding
    ssize_t getPayloadSize(size_t rtp_size) const;
    // 打印调试信息
    std::string dumpString(size_t rtp_size) const;

private:
    // 返回有效负载偏移量
    size_t getPayloadOffset() const;
    // 返回padding长度
    size_t getPaddingSize(size_t rtp_size) const;
};

#pragma pack(pop)

/**
 * rtp 容器类
 */
class RtpBuffer {
public:
    ~RtpBuffer() = default;

    RtpBuffer();

    RtpBuffer(std::string str);

    RtpBuffer& operator=(std::string str);

    RtpBuffer(const char* str);

    RtpBuffer& operator=(const char* str);

    RtpBuffer(RtpBuffer&& that);

    RtpBuffer& operator=(RtpBuffer&& that);

    RtpBuffer(const RtpBuffer& that);

    RtpBuffer& operator=(const RtpBuffer& that);

    char* data() const;

    size_t size() const;

    RtpBuffer& erase(size_t pos = 0, size_t n = std::string::npos);

    RtpBuffer& append(const RtpBuffer& str);

    RtpBuffer& append(const std::string& str);

    RtpBuffer& append(const char* data);

    RtpBuffer& append(const char* data, size_t len);

    void push_back(char c);

    RtpBuffer& insert(size_t pos, const char* s, size_t n);

    RtpBuffer& assign(const char* data);

    RtpBuffer& assign(const char* data, size_t len);

    void clear();

    char& operator[](size_t pos);

    const char& operator[](size_t pos) const;

    size_t capacity() const;

    void reserve(size_t size);

    void resize(size_t size, char c = '\0');

    bool empty() const;

    std::string substr(size_t pos, size_t n = std::string::npos) const;

private:
    void moveData();

private:
    size_t _erase_head;
    size_t _erase_tail;
    std::string _str;
};

/**
 * rtp 分离类
 */
class RtpSpliter {
public:
    RtpSpliter();
    virtual ~RtpSpliter() = default;

    //添加数据
    //实际内存不小于 len + 1
    void input(const char* data, size_t len);

    //收到rtp回调
    virtual ssize_t onRtpPacket(const char* data, size_t len) = 0;

private:

    //恢复初始设置
    void reset();

    //剩余数据大小
    size_t remainDataSize();

    //剩余数据指针
    const char* remainData() const;

    //设置最大缓存大小
    void setMaxCacheSize(size_t max_cache_size);

    //收到rtp头
    ssize_t onRecvHeader(const char* data, size_t len);

    //收到rtp分片或全部数据
    void onRecvContent(const char* data, size_t len);

    //判断数据中是否有包尾
    const char* onSearchPacketTail(const char* data, size_t len);

    //设置 content len
    void setContentLen(ssize_t content_len);

protected:

    //检测是否为RTP包
    bool isRtp(const char* data, size_t len);

private:
    ssize_t _content_len = 0;
    size_t _max_cache_size = 0;
    size_t _remain_data_size = 0;
    size_t _offset = 0;
    RtpBuffer _remain_data;
};

/**
 *  rtp 解析类
 */
class RtpParser : public RtpSpliter {
public:
    RtpParser(bool is_udp);
    ~RtpParser();

    //输入原始流
    void input(const char* data, size_t len);

    //收到rtp回调
    ssize_t onRtpPacket(const char* data, size_t len) override;

private:
    bool _is_udp = false;
    uint32_t _ssrc = 0;
};


#endif //RTPPARSER_RTPPARSER_H
